﻿using System;
using System.Linq;
using System.Text;
using System.Windows;
using System.Reflection;
using AppfabricAdministrator.Commands.Cache;
using AppfabricAdministrator.Entities;

namespace AdminMainUI
{
    /// <summary>
    /// Interaction logic for ConfigWindow.xaml
    /// </summary>
    public partial class ConfigWindow : Window
    {
        private NewCache cacheConfig = null;
        private Boolean existingCache = false;
        private System.Collections.Hashtable hash = null;
        public ConfigWindow()
        {
            InitializeComponent();
            this.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner;
        }

        public ConfigWindow(CacheConfig config)
        {
            InitializeComponent();
            this.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner;

            this.Title = this.Title + " :" + config.CacheName;
            txtCacheName.Text = config.CacheName;
            cmbEviction.SelectedItem = config.Eviction;
            chkExpirable.IsChecked = config.Expirable;
            txtTtl.Text = config.TimeToLive;
            chkHA.IsChecked = config.Secondaries;
            chkNotifications.IsChecked = config.NotificationsEnabled;
            chkReadThrough.IsChecked = config.ReadThroughEnabled;
            chkWriteBehind.IsChecked = config.WriteBehindEnabled;
            txtWBInterval.Text = config.WriteBehindInterval;
            txtWBRetryInterval.Text = config.WriteBehindRetryInterval;
            txtRBCount.Text = config.WriteBehindRetryCount;
            chkPersistSecondary.IsChecked = config.MinSecondaries;
            txtPType.Text = config.ProviderType;
            txtProviderSettings.Text = HashTableToString(config.ProviderSettings);
            existingCache = true;
        }

        public NewCache CreateNewCache()
        {
            this.Title = "New Cache";
            this.ShowDialog();
            return cacheConfig;
        }

        public NewCache SetCacheConfig()
        {
            this.ShowDialog();
            return cacheConfig;
        }

        private void btnOk_Click(object sender, RoutedEventArgs e)
        {
            cacheConfig=new NewCache();
            cacheConfig.Parameters["CacheName"]=txtCacheName.Text;
            cacheConfig.Parameters["Eviction"] = cmbEviction.SelectionBoxItem.ToString();
            cacheConfig.Parameters["Expirable"]=chkExpirable.IsChecked==true?"True":"False";
            cacheConfig.Parameters["MinSecondaries"]=chkPersistSecondary.IsChecked==true?"1":"0";
            cacheConfig.Parameters["NotificationsEnabled"]=chkNotifications.IsChecked==true?"True":"False";

            if (txtProviderSettings.Text=="@{}")
                cacheConfig.Parameters["ProviderSettings"] = hash;
            else
                cacheConfig.Parameters["ProviderSettings"] = null;

            if (!String.IsNullOrEmpty(txtPType.Text))
                cacheConfig.Parameters["ProviderType"] = txtPType.Text;
            else
                cacheConfig.Parameters["ProviderType"] = null;

            cacheConfig.Parameters["ReadThroughEnabled"]=chkReadThrough.IsChecked==true?"True":"False";
            cacheConfig.Parameters["Secondaries"]=chkHA.IsChecked==true?1:0;
            if (chkHA.IsChecked==true)
                cacheConfig.Parameters["Force"] = true;
                
            if (!String.IsNullOrEmpty(txtTtl.Text))
                cacheConfig.Parameters["TimeToLive"] = Int64.Parse(txtTtl.Text);
            else
                cacheConfig.Parameters["TimeToLive"] = 10;
            cacheConfig.Parameters["WriteBehindEnabled"]=chkWriteBehind.IsChecked==true?"True":"False";

            if (!String.IsNullOrEmpty(txtWBInterval.Text))
                cacheConfig.Parameters["WriteBehindInterval"] = Int32.Parse(txtWBInterval.Text);
            else
                cacheConfig.Parameters["WriteBehindInterval"] = 300;

            if (!String.IsNullOrEmpty(txtRBCount.Text))
                cacheConfig.Parameters["WriteBehindRetryCount"] = Int32.Parse(txtRBCount.Text);
            else
                cacheConfig.Parameters["WriteBehindRetryCount"] = -1;

            if (!String.IsNullOrEmpty(txtWBInterval.Text))
                cacheConfig.Parameters["WriteBehindRetryInterval"] = Int32.Parse(txtWBInterval.Text);
            else
                cacheConfig.Parameters["WriteBehindRetryInterval"] = 300;

            if (this.Title != "New Cache")
                cacheConfig.CommandName = "Set-CacheConfig";
            if (existingCache)
                cacheConfig.IsModify = true;
            if (Validate())
            {
                this.Close();
            }
        }

        private String SetProviderSetting(System.Collections.Hashtable _hashTable)
        {
            StringBuilder format = new StringBuilder("@{");
            String valuesFormat="\"{0}\"=\"{1}\";";
            foreach (System.Collections.DictionaryEntry obj in _hashTable)
            {
                format.Append(String.Format(valuesFormat, obj.Key, obj.Value));
            }
            format.Append("}");
            return format.ToString();
        }

        private String HashTableToString(System.Collections.Hashtable _hashTable)
        {
            if (_hashTable == null)
                return null;
            else
            {
                return SetProviderSetting(_hashTable); 
            }
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        private bool Validate()
        {
            if(String.IsNullOrEmpty(txtCacheName.Text.Trim()))
            {
                MessageBox.Show("Cache name cannot be empty.", "Cache Name Mandatory", MessageBoxButton.OK, MessageBoxImage.Information);
                return false;
            }
            if (chkReadThrough.IsChecked==true || chkWriteBehind.IsChecked==true)
            {
                if (String.IsNullOrEmpty(txtPType.Text.Trim()))
                {
                    MessageBox.Show("Provider Type must be specified when the read through or write behind is enabled", "Empty Provider Type", MessageBoxButton.OK, MessageBoxImage.Information);
                    return false;
                }
            }
            return true;
        }

        private void btnAdd_Click(object sender, RoutedEventArgs e)
        {
            if (String.IsNullOrEmpty(txtPKey.Text.Trim()) || String.IsNullOrEmpty(txtPValue.Text.Trim()))
                MessageBox.Show("Key or value cannot be empty");
            else
            {
                if (hash == null)
                    hash = new System.Collections.Hashtable();
                try
                {
                    hash.Add(txtPKey.Text, txtPValue.Text);
                }
                catch (ArgumentException)
                {
                    MessageBox.Show("Item with same key has already been added.", "Item exists", MessageBoxButton.OK, MessageBoxImage.Information);
                }
            }
            txtProviderSettings.Text= SetProviderSetting(hash);
        }

        private void btnClear_Click(object sender, RoutedEventArgs e)
        {
            hash = null;
            txtProviderSettings.Text = "@{}";
        }

        private void btnLoadAssembly_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.Forms.OpenFileDialog dialog = new System.Windows.Forms.OpenFileDialog();
            dialog.Multiselect = false;
            dialog.Filter = "Appfabric Provider (*.dll)|*.dll";
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                AssemblyName an = AssemblyName.GetAssemblyName(dialog.FileName);
                var assembly= Assembly.Load(an);
                Type t=(from Type type in assembly.GetTypes()
                 where type.BaseType.FullName == "Microsoft.ApplicationServer.Caching.DataCacheStoreProvider"
                 select type).FirstOrDefault();
                if (t == null)
                {
                    MessageBox.Show("Could not locate a class in the assembly that implements 'Microsoft.ApplicationServer.Caching.DataCacheStoreProvider'");
                }
                else
                {
                    txtPType.Text = t.FullName + "," + assembly.FullName;
                }
            }
        }
    }
}
